/*+++++++++++++++++++++++++++++++++++++++++
  +                                       +
  + Autore: Davide Gugliotta              +
  + E-mail: dvd.gugliotta@gmail.com       +
  +                                       +
  + FILE: ../tests/scanner_test_syn.c     +
  +                                       +
  + Test per syn scan                     +
  +                                       +
  +++++++++++++++++++++++++++++++++++++++++*/
  
  #include "../modules/scanner.h"
  
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  +                                                                  +
  +  Header necessari per la gestione dei netdevice tramite ioctl(). +
  +  Definisce i tipi struct ifconf e struct ifreq, nonchè tutte le  +
  +  richieste ioctl, tra le quale la SIOCGIFCONF e SIOCGIFADDR.     + 
  +                                                                  +
  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

  #include <sys/ioctl.h>
  #include <net/if.h>

  // numero massimo di interfacce di rete 
  #define MAX_IF_LIST 10

  int main(int argc,char *argv[]){
  
    // variabile per il loop  
    unsigned char i;

    // memorizza il responso della scansione
    unsigned char responso;  
    
    // dichiaro le strutture per la gestione della lista dei network device
    struct ifreq  ifr[MAX_IF_LIST];
    struct ifconf ifc;
 
  /*+++++++++++++++++++++++++++++++++++++++++++++++++++++                                         
    +                                                   +
    + pkt_scan è la struttura che deve essere riempita  +
    + prima di avviare la procedura di scan.            +
    +                                                   +
    + tcp_phdr è la struttura che mantiene il tcp       +
    + pseudo header per il calcolo della                +
    + checksum.                                         +
    +                                                   +
    +++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
  
    struct pkt_scan sp;                                          
    struct tcp_pseudo_header tcp_phdr;
  
    if(argc < 4){
    
      fprintf(stdout, "Usare : ./scanner_test_syn.bin <host> <porta> <interfaccia>\n");
      exit(EXIT_FAILURE);
  
    }
  
    if(atoi(argv[2]) > 65535){
     
      fprintf(stdout, "ricontrollare porta di destinazione..\n");
      exit(EXIT_FAILURE);

    }

    memset(&sp.d_ip, 0, sizeof(struct sockaddr_in)); 
    memset(&tcp_phdr, 0, sizeof(struct tcp_pseudo_header)); 
    
    sp.d_host = gethostbyname(argv[1]);
    if(sp.d_host == NULL){
    
      fprintf(stderr,"gethostbyname() : %s\n",strerror(errno));
      exit(EXIT_FAILURE);
  
    }

  /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +                                                          +
    + Creazione di socket raw (ip) con protocollo  di livello  +
    + superiore TCP.                                           +
    +                                                          +
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/  
  
    sp.socket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    if(sp.socket == -1){
    
      fprintf(stderr, "socket() : %s\n", strerror(errno));
      exit(EXIT_FAILURE);

    }
  
    sp.d_ip.sin_family = AF_INET;
    sp.d_ip.sin_port   = htons(atoi(argv[2]));
    sp.d_ip.sin_addr   = *((struct in_addr *)sp.d_host->h_addr); 
    
    ifc.ifc_len  = MAX_IF_LIST * sizeof(struct ifreq);
    ifc.ifc_buf  = (char *) ifr;  
    
    if(ioctl(sp.socket, SIOCGIFCONF, &ifc) < 0){
      
      fprintf(stderr, "ioctl() : %s\n", strerror(errno));
      exit(EXIT_FAILURE);
    
    }

  /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +                                                             +
    + Seleziono l'interfaccia scelta tra le possibili attive      +
    + sulla macchina, se prensente imposto l'indirizzo di rete    +
    + della stessa come ip sorgente del campo dello psuedo header +
    + il quele serve per il corretto calcolo della checksum tcp.  +
    +                                                             +
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
    for(i=0; i < (ifc.ifc_len / sizeof(struct ifreq)); i++)
      if(strcmp(argv[3], ifc.ifc_req[i].ifr_name) == 0){
	tcp_phdr.ip_src = ((struct sockaddr_in *)&ifc.ifc_req[i].ifr_addr)->sin_addr.s_addr;
	break;
      }
      else 
	if(i == (ifc.ifc_len / sizeof(struct ifreq) - 1)){
	  fprintf(stderr, "Nessuna interfaccia %s presente ...\n", argv[3]);
	  exit(EXIT_FAILURE);
	}
 
  /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +                                                           +
    + Riempio la struttura dello pseudo header TCP composta da: +
    +                                                           +
    + 1) 4 byte indirizzo sorgente (vedi sopra)                 +
    + 2) 4 byte indirizzo destinazione                          +
    + 3) 1 byte di zeri                                         +
    + 4) 1 byte per il protocollo 0x06H = 6DEC                  +
    + 5) 2 byte lunghezza èacchetto  TCP, HEADER + DATI         +
    +                                                           +
    + Nel nostro caso la lunghezza del pacchetto TCP è          +
    + costituita dal solo header 20 byte, il testo è vuoto ,    +
    + è infatti un pacchetto di richiesto nuova connessione.    +
    + Non server trasformare il campo in network byte order     +
    + poichè 20DEC si esprime con 1 byte.                       +
    +                                                           +
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/                    
  
    tcp_phdr.ip_dst  = sp.d_ip.sin_addr.s_addr;
    tcp_phdr.zero    = 0x00;
    tcp_phdr.proto   = 0x06;
    tcp_phdr.tcpht_l = htons(TCP_PKT_H);
  
  /*++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +                                                    +
    + Copio lo pseudo header nel buffer che conterrà     +
    + il pacchetto TCP:                                  +
    +                                                    +
    + TCP_PSUEDO_HEADER (12 byte) + TCP_HEADER (20 byte) +
    +                                                    +
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  
    memcpy(sp.pkt_buffer, &tcp_phdr, TCP_PSEUDO_H);      
 
    // stampo host:ip porta per il debug ;)
    //fprintf(stdout,"%s:%s sulla %hu\n",argv[1],inet_ntoa(sp.d_ip.sin_addr),ntohs(sp.d_ip.sin_port));

    // richiamo la funzione in ../modules/scanner.c
    if((responso = synscan(&sp, 0)) == 1)
      fprintf(stdout, "\n%s:%hu stato [APERTA]\n\n", inet_ntoa(sp.d_ip.sin_addr), ntohs(sp.d_ip.sin_port));
    else if(responso == 0)
      fprintf(stdout, "\n%s:%hu stato [CHIUSA]\n\n", inet_ntoa(sp.d_ip.sin_addr), ntohs(sp.d_ip.sin_port));
    else
      fprintf(stdout, "\n%s:%hu stato [FILTRATA]\n\n", inet_ntoa(sp.d_ip.sin_addr), ntohs(sp.d_ip.sin_port));
    
    return(0);
  
  }
